import {_decorator, Component, Node, Vec3, Prefab} from 'cc';
import {BaseInfoConverter} from "db://assets/scripts/data/converter/BaseInfoConverter";
import {Stage} from "db://assets/scripts/data/model/Stage";
import {StageConverter} from "db://assets/scripts/data/converter/StageConverter";
import {AudioManager} from "db://assets/scripts/common/AudioManager";
import {GameObjectType} from "db://assets/scripts/game/GameObjectType";
import {ResourceUtils} from "db://assets/scripts/common/ResourceUtils";
import {GameManager} from "db://assets/scripts/game/GameManager";
import {CSVManager} from "db://assets/scripts/common/CSVManager";
import {Constants} from "db://assets/scripts/common/Constants";
import {EventType} from "db://assets/scripts/common/EventType";
import {AudioPaths} from "db://assets/scripts/common/AudioPaths";
import {EventManager} from "db://assets/scripts/common/EventManager";
import {MonsterController} from "db://assets/scripts/game/role/monster/MonsterController";
import {PoolManager} from "db://assets/scripts/common/PoolManager";
import {BossController} from "db://assets/scripts/game/role/boss/BossController";

const {ccclass, property} = _decorator;

/**
 * 关卡模型管理脚本（怪物、爱心、障碍、npc）
 */
@ccclass('StageManager')
export class StageManager extends Component {
    /**
     * 待加载的模块种类
     */
    public gameObjectModuleCache: Map<GameObjectType, Stage[]>;
    /**
     * 当前关卡列表
     */
    private stages: Stage[] = [];
    /**
     * 默认暗夜地图节点
     */
    private anNode: Node;
    /**
     * S型暗夜地图节点
     */
    private ansNode: Node;
    /**
     * an地图传送门位置
     */
    private warpGateWorldPosition1: Vec3 = new Vec3(16.414, 1.635, -0.804);
    /**
     * anS地图传送门位置
     */
    private warpGateWorldPosition2: Vec3 = new Vec3(34.61, 1.635, -20);
    /**
     * 传送门
     */
    private warpGateNode: Node;
    /**
     * 存放各项模块节点信息, 除了道路,在玩家后面一定距离则进行回收
     */
    private items: Node[] = [];

    /**
     * 是否是S型暗夜地图
     */
    public static isMapAnS: boolean = false;

    onEnable() {
        EventManager.on(EventType.SHOW_WARP_GATE, this.showWarpGate, this);
        EventManager.on(EventType.HIDE_WARP_GATE, this.hideWarpGate, this);
    }

    onDisable() {
        EventManager.off(EventType.SHOW_WARP_GATE, this.showWarpGate, this);
        EventManager.off(EventType.HIDE_WARP_GATE, this.hideWarpGate, this);
    }

    /**
     * 创建关卡
     *
     * @param stageName 关卡
     * @param onComplete 创建完成时的回调
     */
    public buildStage(stageName: string, onComplete?: Function) {
        // 初始化游戏对象与关卡的信息
        this.gameObjectModuleCache = new Map<GameObjectType, Stage[]>();

        this.items = [];

        // 关卡列表回
        let stageCSV = CSVManager.getInstance().getTable(stageName);
        this.stages = StageConverter.convertFromCSV(stageCSV);

        let callback = () => {
            // 暗夜堡垒大关
            if (stageName.startsWith("map1")) {
                if (this.anNode) {
                    this.anNode.active = false;
                }
                if (this.ansNode) {
                    this.ansNode.active = true;
                }
                StageManager.isMapAnS = true;
            } else {
                // 炼狱大关
                if (this.anNode) {
                    this.anNode.active = true;
                }
                if (this.ansNode) {
                    this.ansNode.active = false;
                }
                StageManager.isMapAnS = false;
            }

            // 游戏对象信息
            let baseInfoCSV = CSVManager.getInstance().getTable("base");
            let baseInfos = BaseInfoConverter.convertFromCSV(baseInfoCSV);
            // 遍历关卡列表
            this.stages.forEach(stage => {
                let baseInfo = baseInfos.find(baseInfo => baseInfo.ID === stage.id);
                if (!this.gameObjectModuleCache.has(baseInfo.type)) {
                    this.gameObjectModuleCache.set(baseInfo.type, []);
                }
                this.gameObjectModuleCache.get(baseInfo.type).push(stage);
            });

            let promises = [];

            this.gameObjectModuleCache.forEach((value, key) => {
                let item = this.gameObjectModuleCache.get(key);
                if (item.length) {
                    promises.push(this.buildModel(key));
                }
            });

            Promise.all(promises).then(() => {
                onComplete && onComplete();
                console.log(`load ${stageName} over`);
            }).catch((e) => {
                console.error("load item module err", e);
            })

            if (!this.warpGateNode) {
                this.initWarpGate();
            }
        }

        // 不同章节加载不同场景
        if (stageName.startsWith("map0") && !this.anNode) {
            // 暗夜
            ResourceUtils.loadModel('scene/an').then((prefab: any) => {
                this.anNode = PoolManager.getInstance().getNode(prefab, this.node.parent);
                callback();
            })
        } else if (stageName.startsWith("map1") && !this.ansNode) {
            // 炼狱
            ResourceUtils.loadModel('scene/anS').then((prefab: any) => {
                this.ansNode = PoolManager.getInstance().getNode(prefab, this.node.parent);
                callback();
            })
        } else {
            callback();
        }
    }

    /**
     * 创建模型
     *
     * @param type 模型类型
     */
    private buildModel(type: GameObjectType) {
        return new Promise((resolve, reject) => {
            // 异步请求
            let promises = [];

            // 同类型的关卡信息
            let stages = this.gameObjectModuleCache.get(type);
            // 初始化关卡列表
            this.gameObjectModuleCache.set(type, []);

            // 游戏基础对象信息
            let baseCSV = CSVManager.getInstance().getTable("base");
            let baseInfos = BaseInfoConverter.convertFromCSV(baseCSV);

            //怪物在该层级别的配置信息
            stages.forEach(stage => {
                //怪物的模块数据
                let baseInfo = baseInfos.find(value => value.ID === stage.id);
                // 模型路径
                let modelPath: string;
                if (Constants.DEBUG) {
                    // 调试模式下的路径
                    modelPath = `${type}02/${baseInfo.resName}`;
                } else {
                    // 正常模式下的路径
                    modelPath = `${type}/${baseInfo.resName}`;
                }

                // 异步请求
                let promise = ResourceUtils.loadModel(modelPath).then((prefab: Prefab) => {
                    // 先创建父节点
                    let parentName = type + 'Group';
                    let parentNode = this.node.getChildByName(parentName);
                    if (!parentNode) {
                        parentNode = new Node(parentName);
                        parentNode.parent = this.node;
                    }

                    // 设置位置、角度、缩放
                    let childNode = PoolManager.getInstance().getNode(prefab, parentNode);
                    let position: Vec3 = stage.position ? stage.position : baseInfo.position;
                    let angle: Vec3 = stage.angle ? stage.angle : baseInfo.angle;
                    let scale: Vec3 = stage.scale ? stage.scale : baseInfo.scale;
                    childNode.setPosition(position);
                    childNode.eulerAngles = angle;
                    childNode.setScale(scale);

                    switch (baseInfo.type) {
                        case GameObjectType.MONSTER:
                            if (!Constants.DEBUG) {
                                let scriptMonster = childNode.getComponent(MonsterController);
                                scriptMonster.init(baseInfo, stage);
                            } else {
                                let scriptMonster = childNode.getComponent(MonsterController);
                                scriptMonster.init(baseInfo, stage);
                            }
                            GameManager.getInstance().gameGetMonsterProxy.getMonsterNodes().push(childNode);
                            break;
                        case GameObjectType.BOSS:
                            GameManager.getInstance().gameGetMonsterProxy.getMonsterNodes().push(childNode);
                            GameManager.getInstance().gameBossProxy.setBossNode(childNode);
                            GameManager.getInstance().gameBossProxy.getBossController().init(baseInfo, stage);
                            break;
                        case GameObjectType.NPC:
                            GameManager.getInstance().gameWarpGateProxy.setExistentNum(GameManager.getInstance().gameWarpGateProxy.getExistentNum() + 1);
                            break;
                        case GameObjectType.HEART:
                            GameManager.getInstance().gameWarpGateProxy.setExistentNum(GameManager.getInstance().gameWarpGateProxy.getExistentNum() + 1);
                            break;
                    }

                    this.items.push(childNode);
                })

                promises.push(promise);
            });

            Promise.all(promises).then(() => {
                resolve(null);
            }).catch((e) => {
                console.error("e", e);
            })
        })
    }

    /**
     * 回收模块
     */
    public recycle() {
        for (let index = 0; index < this.items.length; index++) {
            const element = this.items[index];
            this.recycleModel(element);
        }

        this.node.removeAllChildren();
    }

    /**
     * 回收子模块
     *
     * @param itemNode 子节点
     */
    private recycleModel(itemNode: Node) {
        PoolManager.getInstance().putNode(itemNode);
    }

    /**
     * 初始化传送门
     */
    private initWarpGate() {
        ResourceUtils.loadModel(`warpGate/warpGate`).then((pf: any) => {
            this.warpGateNode = PoolManager.getInstance().getNode(pf, this.node.parent);
            this.warpGateNode.active = false;
        })
    }

    /**
     * 显示传送门
     */
    private showWarpGate() {
        // 播放声音
        AudioManager.getInstance().playSound(AudioPaths.showWarpGateSound);

        // 暗夜堡垒地图
        if (this.anNode && this.anNode.active) {
            this.warpGateNode.setWorldPosition(this.warpGateWorldPosition1);
        } else {
            // 炼狱地图
            this.warpGateNode.setWorldPosition(this.warpGateWorldPosition2);
        }

        // 激活传送门
        this.warpGateNode.active = true;
    }

    /**
     * 隐藏传送门
     */
    private hideWarpGate() {
        if (this.warpGateNode) {
            this.warpGateNode.active = false;
        }
    }
}

